using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class PlayerController:MonoBehaviour {

	public static PlayerController instance;
	private void Update() {
		UpdateInteraction();
		UpdateHandObject();
		HandleInput();
		UpdateSprite();
	}
	private void Awake() {
		instance=this;
		rigidbody=GetComponent<Rigidbody2D>();
		spriteRenderer=GetComponent<SpriteRenderer>();
	}
	private void OnDestroy() {
		instance=null;
	}

	[SerializeField] Sprite[] sprites;
	[SerializeField] AudioClip[] footStepSound;

	[SerializeField] float speed;
	[SerializeField] Transform handTransform;
	public InteractionTarget currentInteractionTarget { get; private set; }
	[HideInInspector] public List<GameObject> inventory = new List<GameObject>();
	[HideInInspector] public GameObject handObject = null;

	new Rigidbody2D rigidbody;
	SpriteRenderer spriteRenderer;
	int imageIndex;
	float timeThisFrame;

	void UpdateSprite() {
		if(sprites.Length==0) return;
		if(rigidbody.velocity.magnitude>0) {
			timeThisFrame+=Time.deltaTime*rigidbody.velocity.magnitude;
			if(timeThisFrame>0.5f) {
				timeThisFrame=0;
				imageIndex=(imageIndex+1)%sprites.Length;
				if(imageIndex==2||imageIndex==6) {
					AudioPlayer.PlayAudio(transform.position,footStepSound[Random.Range(0,footStepSound.Length)],1);
				}
			}

			spriteRenderer.flipX=rigidbody.velocity.x>=0;

		} else {
			timeThisFrame=0;
			imageIndex=0;
		}
		spriteRenderer.sprite=sprites[imageIndex];
	}

	private void UpdateInteraction() {

		currentInteractionTarget=null;
		float currentScore = float.MaxValue;

		foreach(var i in InteractionTarget.instances) {
			if(i.gameObject==handObject) continue;
			if(!i.gameObject.activeInHierarchy) continue;

			Vector3 otherPosition = i.transform.position;
			if(i.TryGetComponent(out Collider2D other)) {
				otherPosition=other.ClosestPoint(transform.position);
			}
			float newDistance = (transform.position-otherPosition).magnitude;

			if(newDistance>1.5f) continue;

			bool isObstructed = false;
			var results = Physics2D.RaycastAll(transform.position,otherPosition-transform.position,newDistance);
			foreach(var hit in results) {
				Collider2D otherCollider = hit.collider;
				if(otherCollider.isTrigger) continue;
				GameObject otherObject = otherCollider.gameObject;
				if(otherObject!=gameObject&&otherObject!=i.gameObject) {
					isObstructed=true;
				}
			}
			if(isObstructed) continue;

			float newScore = newDistance;// +new Angle(i.transform.position-transform.position).degree/30f;
			if(newScore<currentScore) {
				currentScore=newScore;
				currentInteractionTarget=i;
			}
		}


	}

	void HandleInput() {
		rigidbody.velocity=Vector2.zero;
		if(VNController.instance.rootObject.activeInHierarchy) return;
		if(Input.GetKeyDown(KeyCode.Space)&&!VNController.instance.rootObject.activeInHierarchy) {

			if(currentInteractionTarget) currentInteractionTarget.Interact();
			//else if(handObject) DropHandObject();
		}

		Vector2 targetVelocity = Vector2.zero;
		if(Input.GetKey(KeyCode.A)) targetVelocity.x--;
		if(Input.GetKey(KeyCode.D)) targetVelocity.x++;
		if(Input.GetKey(KeyCode.W)) targetVelocity.y++;
		if(Input.GetKey(KeyCode.S)) targetVelocity.y--;
		targetVelocity.Normalize();
		targetVelocity*=speed;
		rigidbody.velocity=targetVelocity;

		if(inventory.Count>0) {
			int originalSlotIndex = inventory.IndexOf(handObject);
			int currentSlotIndex = originalSlotIndex;
			if(currentSlotIndex>=0) {
				if(Input.mouseScrollDelta.y>0) currentSlotIndex+=inventory.Count-1;
				if(Input.mouseScrollDelta.y<0) currentSlotIndex+=1;
				currentSlotIndex%=inventory.Count;
				if(currentSlotIndex!=originalSlotIndex) ChooseInventoryItem(currentSlotIndex);
			}
		}

	}

	public bool AddToInventory(GameObject newItem) {
		if(inventory.Count>=6) return false;
		if(inventory.Contains(newItem)) return false;
		inventory.Add(newItem);
		newItem.transform.position=new Vector3(0,1000000,0);

		string itemName = newItem.name;
		itemName=itemName.Replace("(Clone)","");
		SubtitleController.instance.PushSubtitle(itemName);

		//if(inventory.Count==1) ChooseInventoryItem(0);
		//else 
		ChooseInventoryItem(inventory.IndexOf(newItem));

		return true;
	}

	void ChooseInventoryItem(int index) {
		if(index>=inventory.Count) {
			handObject?.SetActive(false);
			handObject=null;
			return;
		}
		if(handObject) {
			handObject.transform.position=new Vector3(0,1000000,0);
			handObject.SetActive(false);
		}
		handObject=inventory[index];
		if(handObject) {
			handObject.transform.position=handTransform.position;
			handObject.SetActive(true);
			string itemName = handObject.name;
			itemName=itemName.Replace("(Clone)","");
			SubtitleController.instance.PushSubtitle(itemName);
		}
	}

	void UpdateHandObject() {
		inventory.RemoveAll(x => x==null);

		if(handObject==null) return;
		handObject.transform.position=handTransform.position;
		if(handObject.TryGetComponent(out Rigidbody2D handRigidbody)) {
			handRigidbody.simulated=false;
		}

	}

	void DropHandObject() {
		if(handObject==null) return;
		inventory.Remove(handObject);
		if(handObject.TryGetComponent(out Rigidbody2D handRigidbody)) {
			handRigidbody.simulated=true;
		}
		handObject.transform.parent=null;
		handObject.transform.position=transform.position;
		handObject.SetActive(true);
		handObject=null;
		ChooseInventoryItem(0);
	}

	public bool IsHolding(string name) {
		if(!handObject) return false;
		return handObject.name.Contains(name);
	}
	public bool HasItem(string name) {
		if(inventory.Find(x => x.name.Contains(name))) return true;
		return false;
	}

	public bool AddToInventoryFromPrefab(GameObject prefab) {
		if(prefab==null) return false;
		GameObject newGo = Instantiate(prefab,transform.position,Quaternion.identity);
		return AddToInventory(newGo);
	}

	public void RemoveItem(string name) {
		int curIndex = -1;

		for(int i = 0;i<inventory.Count;i++) {
			if(inventory[i].name.Contains(name)) {
				curIndex=i;
				inventory[i].SetActive(false);
			}
		}
		inventory.RemoveAll(x => x.name.Contains(name));
		if(inventory.Count==0) ChooseInventoryItem(0);
		else ChooseInventoryItem((curIndex+1)%inventory.Count);

	}

}
